#!/usr/sbin/rsct/perl5/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2001,2004 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
#"@(#)86   1.12   src/rsct/rm/ConfigRM/cli/bin/startrpnode.perl, configrmcli, rsct_rzauh, rzauh0431a 4/6/04 11:33:09"
######################################################################
#                                                                    #
# Module: startrpnode                                                #
#                                                                    #
# Purpose:                                                           #
#   startrpnode - brings a node online to an RSCT peer domain.       #
#                                                                    #
# Syntax:                                                            #
#   startrpnode  [-h] [-TV] Node_name [Node_name ...]                #
#                                                                    #
#   startrpnode  [-h] -f File | -F file [-TV]                        #
#                                                                    #
# Flags:                                                             #
#   -h      Help. Writes the command's usage statement to standard   #
#           output.                                                  #
#   -f File The file containing the nodes names to be brought online #
#           to the peer domain.  The node names are defined as       #
#           as Node_name operands or in a file, not both.  When in a #
#           file, each line of the file is scanned for one node      #
#           name.  Comments may be placed on each line, but after    #
#           the comment character "#". Lines that start (col 1) with #
#           "#" or are entirely blank are ignored.  Use -f "-" to    #
#           specify STDIN as the input file.                         #
#   -F File Same as -f.                                              #
#   -T      Trace. Writes the command's trace messages to standard   #
#           error. For your software-service organization's use only.#
#   -V      Verbose. Writes the command's verbose messages to        #
#           standard output.                                         #
#                                                                    #
# Operands:                                                          #
#   Node_name   The name of the node to be brought online to the     #
#               peer domain.  The node name is the peer domain node  #
#               name of the node.  The peer domain node names can be #
#               displayed using the lsrpnode command.                #
#                                                                    #
# Description:                                                       #
#   The startrpnode command brings an offline node online to a       #
#   peer domain.  The peer domain is determined by the online peer   #
#   domain of where the command is run.  The command must be run     #
#   from a node that is online to the desired peer domain            #
#                                                                    #
#   The node being brought online must already have been defined to  #
#   be in this peer domain using the mkrpdomain or addrpnode command.#
#   The node must not be online to any other peer domain.            #
#                                                                    #
# Exit Values:                                                       #
#   0  CRM_CLI_SUCCESS       Command completed successfully.         #
#   1  CRM_CLI_RMC_ERROR     Command terminated due to an underlying #
#                            RMC error.                              #
#   2  CRM_CLI_ERROR         Command terminated due to an underlying #
#                            error in the command script.            #
#   3  CRM_CLI_BAD_FLAG      Command terminated due to user          #
#                            specifying an invalid flag.             #
#   4  CRM_CLI_BAD_OPERAND   Command terminated due to user          #
#                            specifying a bad operand.               #
#   5  CRM_CLI_USER_ERROR    Command terminated due to a user error, #
#                            for example specifying a name that      #
#                            already exists.                         #
#                                                                    #
# Examples:                                                          #
#   1. To bring the node nodeB online to the peer domain ApplDomain, #
#      when nodeA is defined and online to ApplDomain, nodeB is      #
#      reachable from nodeA, and nodeB is not online to ApplDomain   #
#      or any other peer domain, run the following comand from       #
#      nodeA:                                                        #
#      startrpnode nodeB                                             #
#                                                                    #
# Man Page:                                                          #
#   For the most current detailed description of this command see    #
#   the startrpnode man page in /usr/sbin/rsct/man.                  #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /usr/sbin/rsct/msgmaps/configrmcli.startrpnode.map -             # 
#       message mapping                                              #
#                                                                    #
# Outputs:                                                           #
#   stdout - none.                                                   #
#   stderr - any error message.                                      #
#                                                                    #
# External Ref:                                                      #
#   Commands: ctdspmsg                                               #
#   Modules:  CRM_cli_utils.pm, CRM_cli_rc.pm,                       #
#             CRM_cli_include.pm, CT_cli_utils.pm                    #
#   Perl library routines: Getopt::Std                               #
#                                                                    #
# Tab Settings:                                                      #
#   4 and tabs should be expanded to spaces before saving this file. #
#   in vi:  (:set ts=4  and   :%!expand -4)                          #
#                                                                    #
# Change Activity:                                                   #
#   010806 JAC 75435: Initial design & write.                        #
#   010827 JAC 75436: Check node list to see if ok to start          #
#   011219 JAC 78807: Don't resolve node names or check if in cluster#
#   020202 JAC 79963: weed out startrsrc error messages.             #
#   020207 JAC 80121: Make printing of c-api results a trace msg.    #
#   020422 JAC 82248: Rename startclnode to startrpnode.             #
#   020428 JAC 82316: Call process_exit_code to check $rc.           #
#   020503 JAC 82564: Set peer domain scope before calling startrsrc.#
#   020530 JAC 82589: Use startrsrc-api instead of startrsrc.        #
#   020711 JAC 84621: Use NodeNameList instead of Name in startrsrc. #
#   040319 JAC 97465: Add -f/-F flags for file input for node names. #
#   040406 JAC 106712: Update usage for file options.                #
######################################################################

#--------------------------------------------------------------------#
# General Program Flow/Logic:                                        #
#                                                                    #
# 1. Parse command line flags and operands.                          #
# 2. Print usage if -h specified                                     #
# 3. Resolve the name of the node the command will run on and make   #
#    sure that it's online in the cluster.                           #
# 4. Resolve the target node names and make sure they are in the     #
#    cluster and not already online                                  #
# 5. Call RMC command startrsrc. Also pass along -VT if necessary.   #
# 6. Return back any errors.                                         #
#                                                                    #
#--------------------------------------------------------------------#

#--------------------------------------------------------------------#
# Included Libraries and Extensions                                  #
#--------------------------------------------------------------------#
use lib "/usr/sbin/rsct/pm";
use locale;
use Getopt::Std;

use CT_cli_utils qw(printIMsg
                    printEMsg);

use CRM_cli_rc qw(CRM_CLI_SUCCESS CRM_CLI_RMC_ERROR
                  CRM_CLI_ERROR CRM_CLI_BAD_FLAG
                  CRM_CLI_BAD_OPERAND CRM_CLI_USER_ERROR);
use CRM_cli_utils qw(error_exit
                     printCIMsg
                     printCEMsg
                     check_node_state
                     check_for_nodes
                     process_api_error
                     process_exit_code
                     get_nodes_nums_from_file
                     get_opstate_by_name);
use CRM_cli_include qw($TRUE $FALSE
                       $RMC_CLI_USER_ERROR
                       $RMC_OPSTATE_ONLINE $RSNODE
                       $PEER_DOMAIN_SCOPE
                       $CTBINDIR $CTDIR);

#--------------------------------------------------------------------#
# Global Variables                                                   #
#--------------------------------------------------------------------#
$Trace = $FALSE;                        # default - trace off
$Verbose = $FALSE;                      # default - verbose turned off
$Opt_File_Input = $FALSE;               # default - no file

$PROGNAME = "startrpnode";              # Program Name for messages
$LSMSG = "$CTBINDIR/ctdspmsg";          # list / display message rtn
$MSGCAT = "configrmcli.cat";            # msg catalogue for this cmd
$ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps";  # msg maps used by $LSMSG

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#
my @node_names = ();                    # nodes to be started
my %node_opstates = ();                 # nodes in cluster
my @node_info = ();                     # nodes in cluster
my $resolved_node_names = "";           # resolved nodelist
my $unresolved_node_names = "";         # unresolved nodelist
my @node_names_to_start = ();           # node names to start
my $one_node = "";                      # one from nodelist
my $node_online = $FALSE;               # boolean
my $in_list = "";                       # reference to array
my $not_in_list = "";                   # reference to array
my @cmd_out = ();                       # output from startrsrc
my @nnodes = ();                        # number of nodes
my $file_name = "";                     # file name for node names
my $file_error = "";                    # error with file
my $node_names_file = "";               # reference to node names
my $node_nums_file = "";                # reference to node numbers
my @node_numbers = ();                  # nodes in cluster

my $passopts = "";                      # TV options to pass to RMC CLI
my $other_opts = "";                    # parameters to pass to RMC CLI
#--------------------------------------------------------------------#
# Main Code                                                          #
#--------------------------------------------------------------------#
my $rc = 0;
my $config_rc = 0;

# set peer domain scope
$ENV{CT_MANAGEMENT_SCOPE} = $PEER_DOMAIN_SCOPE;

# parse the command line, exit if there are errors 
($rc, $file_name, @node_names) = &parse_cmd_line;
($rc == 0) || error_exit($rc);

if ($Verbose) { printIMsg("IMsgstartrpnodeStart",@node_names); }

if ($Trace) { $passopts = $passopts." -T"; }
if ($Verbose) { $passopts = $passopts." -V"; }

# get the nodes opstate info
%node_opstates = get_opstate_by_name($RSNODE);

# make sure there are nodes in the cluster
@nnodes = keys %node_opstates;
if ($#nnodes <0) {
   printCEMsg("EMsgConfigRMcliNoCluster");
   exit (CRM_CLI_USER_ERROR);
}

# get the node names from a file, if specified
if ($Opt_File_Input) {

   # extract the node names from the file
   ($node_names_file, $node_nums_file) = get_nodes_nums_from_file($file_name);

   # copy to other array
   @node_names = @$node_names_file;
   @node_numbers = @$node_nums_file;
}

# make sure the target nodes are in the cluster
($in_list, $not_in_list) = check_for_nodes(\@node_names, \%node_opstates);

# for nodes not in the list (not in the cluster), print error message
foreach $one_node (@$not_in_list) {
   printEMsg("EMsgstartrpnodeNotInCluster",$one_node);
   $config_rc = CRM_CLI_USER_ERROR;
}

# for nodes in the list (in the cluster),
# make sure they're not online and then add to list for starting
foreach $one_node (@$in_list) {
   $node_online = check_node_state($one_node,$RMC_OPSTATE_ONLINE, %node_opstates);
   if ($node_online) {
      printEMsg("EMsgstartrpnodeAlreadyStarted",$one_node);
      $config_rc = CRM_CLI_USER_ERROR;
   }
   # it's offline so add to list to start
   else {
      push (@node_names_to_start, $one_node);
   }
}

# for each node to start, call startrsrc-api
foreach $one_node (@node_names_to_start) {

   if ($Trace) { print STDERR "$PROGNAME: calling startrsrc-api\n";}

   #@cmd_out = `$CTBINDIR/startrsrc $passopts -s "Name==\\\"$one_node\\\"" $RSNODE 2>&1`;

   #@cmd_out=`$CTBINDIR/startrsrc-api -s ${RSNODE}::Name==\\\"${one_node}\\\" 2>&1`;
   @cmd_out=`$CTBINDIR/startrsrc-api -s "${RSNODE}::NodeNameList|<{\\\"${one_node}\\\"}" 2>&1`;

   # capture the return code from startrsrc-api
   $rc = $?;
   $rc = process_exit_code($rc);

   if ($Trace) { print STDERR "startrsrc-api results:\n";
                 print STDERR "@cmd_out";}

   if ($Trace) { print STDERR "$PROGNAME: startrsrc-api returned $rc\n";}

   # show any errors if there was a bad rc
   if ($rc != 0) {
      process_api_error("::",@cmd_out);
   }

   # save rc as ConfigRM CLI user error if it's an RMC CLI user error
   if ($rc == $RMC_CLI_USER_ERROR) {
      $config_rc = CRM_CLI_USER_ERROR;
   }

   # if startrsrc failed, print RMC error message and save rc
   if (($rc != 0) && ($rc != $RMC_CLI_USER_ERROR)) {
#     printCEMsg("EMsgConfigRMcliUnExpectRMCrc",$rc);
      $config_rc = CRM_CLI_RMC_ERROR;
   }
}

if ($Verbose) { printIMsg("IMsgstartrpnodeEnd",@node_names); }

if ($config_rc == 0) { exit($rc); }
else { exit($config_rc); }

#--------------------------------------------------------------------#
# End Main Code                                                      #
#--------------------------------------------------------------------#


#--------------------------------------------------------------------#
# parse_cmd_line - Parse the command line for options and operands.  #
#   Set appropriate global variables as outlined below, make sure we #
#   have a valid combination of arguments / options.                 #
#                                                                    #
# Return:                                                            #
#   $rc   0                  Command line parsed fine, no problem.   #
#         CRM_CLI_BAD_FLAG   Command line contained a bad flag.      #
#   @node_names              Node names to be started.               #
#                                                                    #
# Global Variables Modified:                                         #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#   $Trace             output   True (-T) turn Trace mode on.        #
#   $Opt_File_Input    output   True (-f|-F) file name specified     #
#--------------------------------------------------------------------#
sub parse_cmd_line 
{
my(@original_argv) = @ARGV;
my @node_names = ();                    # nodes to be started
my $file_name = "";                     # file name
my %opts = ();

# Process the command line...
if (!&getopts('hf:F:VT', \%opts)) {     # Gather options; 
                                        # if errors
    &print_usage;                       # display proper usage
    return CRM_CLI_BAD_FLAG;            # return bad rc - bad flag 
}

# process h flag
if (defined $opts{h}) {                 # -h, help request
    &print_usage;                       # print usage statement
    exit(0);                            # all done with good return!
}

if (defined $opts{T}) {                 # -T turn trace on
    $Trace = $TRUE;
}

if (defined $opts{V}) {                 # -V turn verbose mode on
    $Verbose = $TRUE;
}

# Get the arguments...
# Operands:  node names
if ($#ARGV >= 0) {                      # node names   
   @node_names = @ARGV;                 # get node names
}

# make sure -f or -F for file used if there are no node names
if (($#node_names < 0) && !(defined $opts{f}||defined $opts{F})) {
    printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands");
    &print_usage;
    return CRM_CLI_BAD_OPERAND;
}

if (defined $opts{f}) {                 # -f for file

    # make sure both -f and -F not used together
    if (defined $opts{F}) {
       printCEMsg("EMsgConfigRMcliImproperUsageCombination","-f","-F");
       &print_usage;
       return CRM_CLI_BAD_FLAG;
   }
    $Opt_File_Input = $TRUE;
    $file_name = $opts{f};
    # make sure file and cmd line not both used for node names
    if ($#node_names >= 0) {
       printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands");
       &print_usage;
       return CRM_CLI_BAD_OPERAND;
   }
}

if (defined $opts{F}) {                 # -F for file
    $Opt_File_Input = $TRUE;
    $file_name = $opts{F};
    # make sure file and cmd line not both used for node names
    if ($#node_names >= 0) {
       printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands");
       &print_usage;
       return CRM_CLI_BAD_OPERAND;
   }
}

return(0, $file_name, @node_names);         # success

}   # end parse_cmd_line


#--------------------------------------------------------------------#
# print_usage : print the usage statement (syntax) to stdout.        #
#--------------------------------------------------------------------#
sub print_usage
{
&printIMsg("IMsgstartrpnodeUsageF");
}   # end print_usage

